package com.shenmazong.serverwebpoem.task;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shenmazong.serverwebpoem.game.ChoiceQuestionWebSocket;
import com.shenmazong.serverwebpoem.game.GameConst;
import com.shenmazong.serverwebpoem.mapper.ITbGameRoomMapper;
import com.shenmazong.serverwebpoem.mapper.ITbPoetryMapper;
import com.shenmazong.serverwebpoem.mapper.ITbQuestionMapper;
import com.shenmazong.serverwebpoem.mapper.ITbRecordGameMapper;
import com.shenmazong.serverwebpoem.pojo.*;
import com.shenmazong.serverwebpoem.service.ElasticSearchService;
import com.shenmazong.serverwebpoem.service.TbPoetryInfoService;
import com.shenmazong.serverwebpoem.service.TbPoetryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

/**
 * @author 田不平
 * @project server-web-poem
 * @date 2020/3/27 8:59 AM
 * http://www.shenmazong.com
 */

@Slf4j
@Service
public class TaskThreadService {

    @Autowired
    private TbPoetryService tbPoetryService;

    @Autowired
    private TbPoetryInfoService tbPoetryInfoService;

    @Autowired
    private ElasticSearchService elasticSearchService;

    @Autowired
    ITbPoetryMapper iTbPoetryMapper;

    @Autowired
    ITbQuestionMapper iTbQuestionMapper;

    @Autowired
    ITbGameRoomMapper iTbGameRoomMapper;

    @Autowired
    ITbRecordGameMapper iTbRecordGameMapper;

    /**
     * TODO 定时存储诗词
     */
    @Async
    public void startThreadSavePoeties() {
        log.info("[save] startThreadSavePoeties begin");

        try {
            Integer idx = 1;
            TbPoetryInfo info = new TbPoetryInfo();

            do {

                // 获取诗词列表
                //IPage<TbPoetry> iPage = tbPoetryService.getList4NotInElastic(idx, 10);
                //List<TbPoetry> poetries = iPage.getRecords();
                List<TbPoetry> poetries = tbPoetryService.getList4EsIsNULL();
                if(poetries == null || poetries.size() == 0) {
                    Thread.sleep(1000*60);
                    continue;
                }

                // 循环保存到elasticsearch中
                // 可以一次性保存到库中
                for (TbPoetry poetry : poetries) {
                    elasticSearchService.saveDoc(poetry);
                    log.info("save:" + poetry.getTitle());

                    TbPoetryInfo tpi = tbPoetryInfoService.getByPoetryId(poetry.getId());
                    if(tpi == null) {
                        info.setPoetryid(poetry.getId());
                        info.setEs(1);
                        tbPoetryInfoService.add(info);
                    }
                    else {
                        tpi.setPoetryid(poetry.getId());
                        tpi.setEs(1);
                        tbPoetryInfoService.set(tpi);
                    }

                    //Thread.sleep(10 * 1);
                }

                // 如果是最后一页，则结束
                //if (idx == iPage.getPages())
                //    break;
                //idx ++;
            } while (true);

        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return;
    }

    /**
     * TODO 生成问题任务
     */

    @Async
    public void startThreadMakeQuestions() {
        log.info("[question] startThreadMakeQuestions begin");
        try {
            do {
                if(makeAskSelectQuestion() == 0)
                {
                    log.info("startThreadMakeQuestions : waiting ...");
                    Thread.sleep(1000*60);
                }
            } while (true);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * TODO 生成选择题
     */
    private Integer makeAskSelectQuestion() {
        Random rand = new Random();

        //--1 查找没有生成的诗词
        Page<TbPoetry> page = new Page<>(1, 10);
        IPage<TbPoetry> iPage = iTbPoetryMapper.selectList4NotInQuestion(page);

        if(iPage.getPages() <= 0) {
            return 0;
        }

        //-- 2 循环生成试题
        List<TbPoetry> poetries = iPage.getRecords();
        for(TbPoetry poetry : poetries) {
            TbPoetryInfo info = tbPoetryInfoService.getByPoetryId(poetry.getId());
            if(info == null) {
                continue;
            }
            String content = poetry.getContent();

            // 分句
            String[] segments = content.split("。");
            for(String ment:segments) {
                int key = 0;
                String word = "";
                char[] charArray = ment.toCharArray();
                // 选字
                do {
                    int ndx = rand.nextInt(charArray.length-1);
                    if (java.lang.Character.toString(charArray[ndx]).matches("[\\u4E00-\\u9FA5]+")) {
                        key = ndx;
                        word = charArray[ndx]+"";
                        break;
                    }
                }while (true);

                // 生成题目
                String title = ment.replaceFirst(word,"( )") + "。";

                // 生成混淆答案(从整首诗中混淆)
                String strReply = content.replace(word, "AA");
                char[] wordArray = strReply.toCharArray();

                List<String> hashReply = new ArrayList<>();
                for(int idx=0; idx<wordArray.length; idx++) {
                    if (java.lang.Character.toString(wordArray[idx]).matches("[\\u4E00-\\u9FA5]+")) {
                        hashReply.add(wordArray[idx]+"");
                    }
                }
                for(int idx=0; idx<10; idx++)
                    Collections.shuffle(hashReply);

                // 组成真正答案
                List<String> realReply = new ArrayList<>();

                for(String srp : hashReply) {
                    realReply.add(srp);
                    if(realReply.size() >= 3) {
                        break;
                    }
                }
                realReply.add(word);
                if(realReply.size() != 4) {
                    // 字数不够，忽略
                    continue;
                }
                Collections.shuffle(realReply);

                // 查找真正答案
                for (int adx=0; adx<realReply.size(); adx++) {
                    if(word.equals(realReply.get(adx))) {
                        key = adx + 1;
                        break;
                    }
                }

                // 存入题库
                TbQuestion question = new TbQuestion();
                question.setPoetryid(poetry.getId());
                question.setQuestion(title);
                question.setAnswer(key);
                question.setReply1(realReply.get(0));
                question.setReply2(realReply.get(1));
                question.setReply3(realReply.get(2));
                question.setReply4(realReply.get(3));
                question.setAskrank(info.getDifficult());

                iTbQuestionMapper.insert(question);
            }
        }

        return poetries.size();
    }

    /**
     * TODO 监控比赛房间
     */
    @Async
    void startThreadGameRoom() {

        // 清空残留房间
        iTbGameRoomMapper.delete(
                new QueryWrapper<TbGameRoom>().eq("status", GameConst.GAME_ROOM_STATUS_READY)
        );

        // 开始准备比赛房间
        do {
            try {
                // 检查是否有可进入房间
                if(ChoiceQuestionWebSocket.waitRoom == null) {
                    // 没有可进入房间，则创建房间
                    TbGameRoom room = new TbGameRoom();
                    room.setStatus(GameConst.GAME_ROOM_STATUS_READY);
                    iTbGameRoomMapper.insert(room);

                    room.setRoomid(room.getId());
                    iTbGameRoomMapper.updateById(room);

                    // 创建比赛线程
                    ChoiceQuestionWebSocket.waitRoom = room;
                    this.startThreadGameRace(room);

                    // 等待比赛线程初始化
                    Thread.sleep(1000*20);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            try {
                Thread.sleep(1000*10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        } while (true);
    }

    /**
     * TODO 启动比赛线程
     * @param room
     */
    @Async
    void startThreadGameRace(TbGameRoom room) {
        //-- 变更比赛房间状态
        room.setStatus(GameConst.GAME_ROOM_STATUS_READY);
        iTbGameRoomMapper.updateById(room);


        //-- 准备考题
        List<TbQuestion> asks = iTbQuestionMapper.selectList(
                new QueryWrapper<TbQuestion>()
                        .orderByAsc("RAND()")
                        .last("limit 10")
        );
        //-- 试题不足
        if(asks.size() != 10) {
            room.setStatus(GameConst.GAME_ROOM_STATUS_END);
            iTbGameRoomMapper.updateById(room);
        }

        try {
            //-- 等待比赛
            do {
                log.info("Room:{} waiting ...", room.getRoomid());
                long waitTime = System.currentTimeMillis();
                //-- 等待比赛（2分钟）
                do {
                    long nowTime = System.currentTimeMillis();
                    long leftTime = 1000*60*2 - (nowTime - waitTime);
                    if(leftTime >= 0) {
                        break;
                    }
                    // 每5秒发一次通知
                    ChoiceQuestionWebSocket.sendRaceReadyByRoomId(room.getRoomid(), leftTime);
                    Thread.sleep(1000*5);
                } while (true);

                // 检查参赛人数
                Integer count = ChoiceQuestionWebSocket.getUserCountByRoomId(room.getRoomid());
                if(count <= 0) {
                    // 没人参赛，继续等待2分钟
                    continue;
                }

                // 变更比赛状态:正在比赛

                room.setStatus(GameConst.GAME_ROOM_STATUS_WORKING);
                iTbGameRoomMapper.updateById(room);

                ChoiceQuestionWebSocket.waitRoom = null;
                ChoiceQuestionWebSocket.raceRoom = room;

                // 发送准备通知（9秒钟准备）
                for(Integer idx=0; idx<3; idx++) {
                    ChoiceQuestionWebSocket.sendRaceReadyByRoomId(room.getRoomid(), 0L);
                    // 每5秒发一次通知
                    Thread.sleep(1000*3);
                }

                // 发送比赛开始命令
                ChoiceQuestionWebSocket.sendRaceStartByRoomId(room.getRoomid(), asks.size());

                for(TbQuestion ask : asks) {
                    // 发送试题
                    ChoiceQuestionWebSocket.sendRaceQuestionByRoomId(room.getRoomid(), ask);



                    for(Integer idx=0; idx<5; idx++) {
                        // 收集得分情况/计算排名/发送排名
                        Thread.sleep(1000*3);
                        ChoiceQuestionWebSocket.sendRaceUserScoreTop(room.getRoomid());

                    }
                }

                // 发送最终比赛排名
                Thread.sleep(1000*3);
                ChoiceQuestionWebSocket.sendRaceUserScoreTop(room.getRoomid());

                // 发送比赛结束命令
                ChoiceQuestionWebSocket.sendRaceGameEnd(room.getRoomid());

                // 变更比赛状态:比赛结束
                room.setStatus(GameConst.GAME_ROOM_STATUS_END);
                iTbGameRoomMapper.updateById(room);
                ChoiceQuestionWebSocket.raceRoom = null;
                break;

            } while (true);
        } catch (InterruptedException e) {
            log.info("startThreadGameRace:"+e);
            e.printStackTrace();
        }
    }
}
